package com.kj.tms.common.utils.calx.util;

import com.kj.tms.common.utils.NumberUtils;
import com.kj.tms.common.utils.StringUtil;
import com.kj.tms.common.utils.calx.formula.Logical;
import com.kj.tms.common.utils.calx.formula.Statistic;
import com.kj.tms.common.utils.calx.sheet.Sheet;
import com.kj.tms.common.utils.calx.formula.Math;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @ProjectName: ledger
 * @Package: com.hongtu.tms.ledger.calx.factory
 * @ClassName: FormulaFactory
 * @Description: [excel函数工厂]
 * @Author: [zhuyongjie]
 * @CreateDate: 2018/4/17 9:07
 * @UpdateUser: []
 * @UpdateDate: 2018/4/17 9:07
 * @UpdateRemark: []
 * @Version: 1.0
 * Copyright: 北京宏图天安 Copyright (c) 2018
 */
public class FormulaFactory {

    /**
     * @Method      callFunction
     * @Param		functionName 方法名称
     * @Param		params
     * @Param		sheet
     * @Return      java.lang.Object
     * @Exception
     * @Description [调用函数执行方法]
     * @Author      zhuyongjie
     * @Version     1.0
     * @Date        2018/4/17 9:27
     */
    public static Object callFunction(String functionName, Object params, Sheet sheet) throws Exception {
        functionName = functionName.toUpperCase();
        switch (functionName){
            /**********函数运算**************/
            case "SUM"://求和
                if(params instanceof HashMap){
                    Map map = (HashMap) params;
                    List<Map<String,Object>> list = new ArrayList<>();
                    list.add(map);
                    return Math.SUM(list);
                }else if(params instanceof ArrayList){
                    List list = (ArrayList) params;
                    return Math.SUM(list);
                }
                break;
            case "SUMIF":
              if(params instanceof ArrayList){
                  List sumifList = (ArrayList) params;
                  Map<String,Object> rangeMap = null;
                  Map<String,Object> sumRangeMap = null;
                  String criteria = "";
                  if(!StringUtil.isEmptyOrNull(sumifList) && sumifList.size() == 3){
                      if(sumifList.get(0) instanceof HashMap){
                          rangeMap = (HashMap<String,Object>) sumifList.get(0);
                      }
                      if(sumifList.get(1) instanceof String){
                          criteria = StringUtil.toString(sumifList.get(1));
                      }
                      if(sumifList.get(2) instanceof HashMap){
                          sumRangeMap = (HashMap<String,Object>) sumifList.get(2);
                      }
                      if((!StringUtil.isEmptyOrNull(rangeMap) && rangeMap.size() > 0)
                              && (!StringUtil.isEmptyOrNull(criteria))
                              && (!StringUtil.isEmptyOrNull(sumRangeMap) && sumRangeMap.size() > 0)){
                          return Math.SUMIF(rangeMap,criteria,sumRangeMap,sheet);
                      }
                  }else if(!StringUtil.isEmptyOrNull(sumifList) && sumifList.size() == 2){
                      if(sumifList.get(0) instanceof HashMap){
                          rangeMap = (HashMap<String,Object>) sumifList.get(0);
                      }
                      if(sumifList.get(1) instanceof String){
                          criteria = StringUtil.toString(sumifList.get(1));
                      }
                      if((!StringUtil.isEmptyOrNull(rangeMap) && rangeMap.size() > 0)
                              && (!StringUtil.isEmptyOrNull(criteria))){
                          return Math.SUMIF(rangeMap,criteria,rangeMap,sheet);
                      }
                  }//if end
              }//if end
                break;
            case "SUMIFS":
                if(params instanceof ArrayList){
                    List sumifsList = (ArrayList) params;
                    return Math.SUMIFS(sumifsList,sheet);
                }//if end
                break;
            case "ABS"://绝对值
                if(params instanceof Integer
                        || params instanceof String){
                    return Math.ABS(StringUtil.toString(params));
                }//if end
                break;
            case "MOD" ://求余
                if(params instanceof ArrayList){
                    ArrayList modList = (ArrayList) params;
                    if(!StringUtil.isEmptyOrNull(modList) && modList.size() > 1){
                        return Math.MOD(StringUtil.toDouble(modList.get(0)),
                                StringUtil.toDouble(modList.get(1)));
                    }//if end
                }//if end
                break;
            case "POWER"://幂运算
                if(params instanceof ArrayList){
                    List powerList = (ArrayList) params;
                    if(!StringUtil.isEmptyOrNull(powerList) && powerList.size() > 1){
                        return Math.POWER(StringUtil.toDouble(powerList.get(0)),
                                StringUtil.toDouble(powerList.get(1)));
                    }//if end
                }//if end
                break;
            case "ROUND":
                if(params instanceof ArrayList){
                    ArrayList roundList = (ArrayList) params;
                    if(!StringUtil.isEmptyOrNull(roundList) && roundList.size() > 1){
                        return Math.ROUND(StringUtil.toDouble(roundList.get(0)),
                                StringUtil.toDouble(roundList.get(1)));
                    }//if end
                }//if end
                break;
            case "ROUNDDOWN":
                if(params instanceof ArrayList){
                    ArrayList roundList = (ArrayList) params;
                    if(!StringUtil.isEmptyOrNull(roundList) && roundList.size() > 1){
                        return Math.ROUNDDOWN(StringUtil.toDouble(roundList.get(0)),
                                StringUtil.toDouble(roundList.get(1)));
                    }//if end
                }//if end
                break;
            case "ROUNDUP" :
                if(params instanceof ArrayList){
                    ArrayList roundList = (ArrayList) params;
                    if(!StringUtil.isEmptyOrNull(roundList) && roundList.size() > 1){
                        return Math.ROUNDUP(StringUtil.toDouble(roundList.get(0)),
                                StringUtil.toDouble(roundList.get(1)));
                    }//if end
                }//if end
                break;
            /**********函数运算 END **************/

            /**********逻辑运算**************/
            case "AND":
                if(params instanceof ArrayList){
                    List orList = (ArrayList) params;
                    return Logical.AND(orList);
                }else if(params instanceof Boolean){
                    List orList = new ArrayList();
                    orList.add(params);
                    return Logical.AND(orList);
                }//if end
                break;
            case "FALSE":
                return Logical.FALSE();
            case "IF":
                if(params instanceof ArrayList){
                    ArrayList ifList = (ArrayList) params;
                    if(ifList.size() == 1){
                        return Logical.IF(StringUtil.toString(ifList.get(0)),"","");
                    }else if(ifList.size() == 2){
                        return Logical.IF(StringUtil.toString(ifList.get(0))
                                ,StringUtil.toString(ifList.get(1))
                                ,"");
                    }else if(ifList.size() > 2){
                        return Logical.IF(StringUtil.toString(ifList.get(0))
                                ,StringUtil.toString(ifList.get(1))
                                ,StringUtil.toString(ifList.get(2)));
                    }//if end
                }else if(params instanceof Boolean){
                    return Logical.IF(StringUtil.toString(params),"","");
                }//if end
                break;
            case "NOT":
                if(params instanceof Boolean){
                    return Logical.NOT(Boolean.parseBoolean(StringUtil.toString(params)));
                }else if(params instanceof String){
                    String str = StringUtil.toString(params).toUpperCase();
                    if(!str.equals("TRUE") && !str.equals("FALSE")){
                        return Logical.NOT(true);
                    }else{
                        return Logical.NOT(Boolean.parseBoolean(str));
                    }//if end
                }//if end
                break;
            case "OR":
                if(params instanceof ArrayList){
                    List orList = (ArrayList) params;
                    return Logical.OR(orList);
                }else if(params instanceof Boolean){
                    List orList = new ArrayList();
                    orList.add(params);
                    return Logical.OR(orList);
                }//if end
                break;
            case "TRUE":
                return Logical.TRUE();

            /**********逻辑运算END**************/

            /**********统计运算**************/
            case "AVERAGE":
                //平均数
                if(params instanceof ArrayList){
                    List averageList = (ArrayList) params;
                    Double average = Statistic.AVERAGE(averageList);
                    if(!StringUtil.isEmptyOrNull(average)){
                        return average;
                    }//if end
                }else if(params instanceof String){
                    String averageStr = StringUtil.toString(params);
                    if(NumberUtils.isRealNumber(averageStr)){
                        return averageStr;
                    }//if end
                }//if end
                break;
            case "COUNT":
                Integer count = Statistic.COUNT(params);
                if(!StringUtil.isEmptyOrNull(count)){
                    return count;
                }//if end
                break;
            /**********统计运算 END**************/
        }//switch end
        return "#NAME?";
    }
}
